package incrpatch

import (
	"strings"
)

// IncrRecords 数据增量记录表
// 用于存储一个文档型数据结构中的字段级增量标记，包括对每个字段的更新和删除的增量版本号
type IncrRecords struct {
	records map[string]int
}

// NewIncrRecords IncrRecords 构造函数
func NewIncrRecords() *IncrRecords {
	return &IncrRecords{
		records: make(map[string]int),
	}
}

// Dirty 是否有脏标记，有任何改动记录都表示有脏数据
func (r *IncrRecords) Dirty() bool { return len(r.records) > 0 }

// Reset 重置记录表为初始状态
func (r *IncrRecords) Reset() { r.records = make(map[string]int) }

// check 检查已存在的改动记录中，是否存在指定key的父节点或子节点
// 如果已经存在指定 key 的父级节点的更新记录，则不需要再记录此子节点更新
// 如果已经存在指定 key 的子节点的更新记录，则将他们全部删除
func (r *IncrRecords) check(key string) bool {
	var list []string
	for ek := range r.records {
		// 如果已经存在指定 key 的父级节点的更新记录
		if strings.HasPrefix(key, ek+".") {
			return false
		}
		// 如果已经存在指定 key 的子节点的更新记录
		if strings.HasPrefix(ek, key+".") {
			list = append(list, ek)
		}
	}
	for _, ek := range list {
		delete(r.records, ek)
	}
	return true
}

// Update 指定的字段更新
func (r *IncrRecords) Update(key string) {
	key = strings.ToLower(key)
	if !r.check(key) {
		return
	}
	ver := r.records[key]
	r.records[key] = abs(ver) + 1
}

// Delete 指定的字段删除
func (r *IncrRecords) Delete(key string) {
	key = strings.ToLower(key)
	if !r.check(key) {
		return
	}
	ver := r.records[key]
	r.records[key] = -(abs(ver) + 1)
}

// abs 整数的绝对值
func abs(v int) int {
	if v >= 0 {
		return v
	}
	return -v
}
